<template>
  <div class="earth-container">
    <div id="opaque-earth-canvas" ref="earthCanvas"></div>
    <div class="controls">
      <button @click="toggleRotation">{{ isRotating ? '暂停旋转' : '开始旋转' }}</button>
      <button @click="resetView">重置视角</button>
      <button @click="toggleWireframe">{{ showWireframe ? '实体模式' : '线框模式' }}</button>
      <button @click="toggleTexture">{{ showTexture ? '纯色模式' : '纹理模式' }}</button>
      <button @click="toggleGeoLayer">{{ showGeoLayer ? '隐藏地理层' : '显示地理层' }}</button>
    </div>
    <div class="info">
      <p>鼠标拖拽旋转 | 滚轮缩放</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'

// 响应式变量
const earthCanvas = ref<HTMLElement | null>(null)
const isRotating = ref(true)
const showWireframe = ref(false)
const showTexture = ref(true)
const showGeoLayer = ref(true)

// Three.js 变量
let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let earth: THREE.Mesh
let controls: OrbitControls
let animationId: number
let earthMaterial: THREE.MeshPhongMaterial
let geoGroup: THREE.Group

// 初始化Three.js场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x000814) // 深蓝色背景

  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  )
  camera.position.z = 3

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.shadowMap.enabled = true
  renderer.shadowMap.type = THREE.PCFSoftShadowMap
  earthCanvas.value?.appendChild(renderer.domElement)

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  controls.dampingFactor = 0.05
  controls.enableZoom = true
  controls.minDistance = 1.5
  controls.maxDistance = 10
  controls.enablePan = false

  // 创建地球
  createEarth()

  // 添加简化光源
  addLights()

  // 添加星空背景
  //createStarfield()

  // 移除大气层效果以减少立体感
  // createAtmosphere()

  // 添加简化云层
  //createClouds()

  // 添加地理数据层
  createGeoLayer()
}

// 创建不透明地球
function createEarth() {
  // 减少球体细分数量以降低立体效果
  const geometry = new THREE.SphereGeometry(1, 32, 32)
  
  // 加载地球纹理
  const textureLoader = new THREE.TextureLoader()
  const earthTexture = textureLoader.load(`${location.origin}/src/assets/img/earth.jpg`)
  // 移除法线贴图以减少立体效果
  // const normalTexture = textureLoader.load(`${location.origin}/src/assets/img/earthNormal.jpg`)
  const specularTexture = textureLoader.load(`${location.origin}/src/assets/img/earth-glow.jpg`)
  
  // 创建不透明材质，调整属性以减少立体效果
  earthMaterial = new THREE.MeshPhongMaterial({
    map: earthTexture,
    // 移除法线贴图
    // normalMap: normalTexture,
    specularMap: specularTexture,
    specular: new THREE.Color(0x666666), // 降低高光强度
    shininess: 5, // 降低光泽度
    flatShading: true, // 使用平面着色而非光滑着色
    transparent: false, // 不透明
    opacity: 1.0,      // 完全不透明
    wireframe: showWireframe.value
  })

  earth = new THREE.Mesh(geometry, earthMaterial)
  earth.castShadow = true
  earth.receiveShadow = true
  scene.add(earth)
}

// 添加简化光源
function addLights() {
  // 增强环境光以减少阴影效果
  const ambientLight = new THREE.AmbientLight(0x404040, 0.8)
  scene.add(ambientLight)

  // 简化主方向光（太阳光）
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.6)
  directionalLight.position.set(5, 3, 5)
  directionalLight.castShadow = false // 关闭阴影以减少立体感
  scene.add(directionalLight)

  // 移除补充光和边缘光以减少复杂光照效果
  // 补充光
  // const fillLight = new THREE.DirectionalLight(0x87ceeb, 0.3) // 天蓝色补充光
  // fillLight.position.set(-5, -3, -5)
  // scene.add(fillLight)

  // 边缘光
  // const rimLight = new THREE.DirectionalLight(0xffa500, 0.2) // 橙色边缘光
  // rimLight.position.set(0, -5, 0)
  // scene.add(rimLight)
}

// 创建简化星空背景
function createStarfield() {
  const starsGeometry = new THREE.BufferGeometry()
  const starsMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.01, // 减小星星尺寸
    transparent: true,
    opacity: 0.5 // 降低透明度
  })

  // 减少星星数量以简化背景
  const starsVertices = []
  for (let i = 0; i < 5000; i++) {
    const x = (Math.random() - 0.5) * 2000
    const y = (Math.random() - 0.5) * 2000
    const z = (Math.random() - 0.5) * 2000
    starsVertices.push(x, y, z)
  }

  starsGeometry.setAttribute('position', new THREE.Float32BufferAttribute(starsVertices, 3))
  const stars = new THREE.Points(starsGeometry, starsMaterial)
  scene.add(stars)
}

// 创建大气层效果
function createAtmosphere() {
  const atmosphereGeometry = new THREE.SphereGeometry(1.15, 64, 64)
  const atmosphereMaterial = new THREE.ShaderMaterial({
    vertexShader: `
      varying vec3 vNormal;
      void main() {
        vNormal = normalize(normalMatrix * normal);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `,
    fragmentShader: `
      varying vec3 vNormal;
      void main() {
        float intensity = pow(0.6 - dot(vNormal, vec3(0, 0, 1.0)), 2.0);
        gl_FragColor = vec4(0.3, 0.6, 1.0, 1.0) * intensity;
      }
    `,
    blending: THREE.AdditiveBlending,
    side: THREE.BackSide,
    transparent: true,
    opacity: 0.3
  })
  
  const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial)
  scene.add(atmosphere)
}

// 创建简化云层
function createClouds() {
  // 减少云层球体的细分以降低立体感
  const cloudGeometry = new THREE.SphereGeometry(1.05, 32, 32)
  const textureLoader = new THREE.TextureLoader()
  
  // 创建简化云层纹理（使用程序化纹理）
  const cloudCanvas = document.createElement('canvas')
  cloudCanvas.width = 256
  cloudCanvas.height = 128
  const ctx = cloudCanvas.getContext('2d')!
  
  // 简化云层图案
  ctx.fillStyle = 'white'
  for (let i = 0; i < 50; i++) {
    const x = Math.random() * 256
    const y = Math.random() * 128
    const radius = Math.random() * 15 + 3
    ctx.globalAlpha = Math.random() * 0.3 + 0.1
    ctx.beginPath()
    ctx.arc(x, y, radius, 0, Math.PI * 2)
    ctx.fill()
  }
  
  const cloudTexture = new THREE.CanvasTexture(cloudCanvas)
  
  const cloudMaterial = new THREE.MeshPhongMaterial({
    map: cloudTexture,
    transparent: true,
    opacity: 0.2, // 降低云层透明度
    depthWrite: false,
    flatShading: true // 使用平面着色
  })
  
  const clouds = new THREE.Mesh(cloudGeometry, cloudMaterial)
  scene.add(clouds)
}

// 创建地理数据层
function createGeoLayer() {
  geoGroup = new THREE.Group()
  
  // 加载地理数据
  fetch('/src/assets/json/worldGeoData.json')
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      return response.json()
    })
    .then(data => {
      console.log('地理数据加载成功:', data.features.length, '个国家')
      const features = data.features
      
      features.forEach((feature: any, index: number) => {
        const geometry = feature.geometry
        const properties = feature.properties
        const countryName = properties.name
        
        // 为每个国家生成独特的颜色
        const color = generateCountryColor(countryName)
        
        console.log(`处理国家: ${countryName}`)
        
        if (geometry.type === 'Polygon') {
          createCountryMesh(geometry.coordinates[0], color, countryName)
        } else if (geometry.type === 'MultiPolygon') {
          geometry.coordinates.forEach((polygon: any) => {
            createCountryMesh(polygon[0], color, countryName)
          })
        }
      })
      
      console.log('地理区域层创建完成，共添加了', geoGroup.children.length, '个国家')
      // 将地理区域层添加到地球
      earth.add(geoGroup)
    })
    .catch(error => {
      console.error('加载地理数据失败:', error)
      // 尝试使用相对路径
      console.log('尝试使用相对路径加载...')
      fetch('./src/assets/json/worldGeoData.json')
        .then(response => response.json())
        .then(data => {
          console.log('使用相对路径加载成功')
          // 重新处理数据
          const features = data.features
          features.forEach((feature: any) => {
            const geometry = feature.geometry
            const properties = feature.properties
            const countryName = properties.name
            const color = generateCountryColor(countryName)
            
            if (geometry.type === 'Polygon') {
              createCountryMesh(geometry.coordinates[0], color, countryName)
            } else if (geometry.type === 'MultiPolygon') {
              geometry.coordinates.forEach((polygon: any) => {
                createCountryMesh(polygon[0], color, countryName)
              })
            }
          })
          earth.add(geoGroup)
        })
        .catch(err => {
          console.error('相对路径也失败:', err)
        })
    })
}

// 为国家生成独特的颜色
function generateCountryColor(countryName: string): THREE.Color {
  // 使用国家名称的哈希值生成颜色
  let hash = 0
  for (let i = 0; i < countryName.length; i++) {
    hash = countryName.charCodeAt(i) + ((hash << 5) - hash)
  }
  
  // 生成鲜艳的颜色
  const hue = Math.abs(hash) % 360
  const saturation = 60 + (Math.abs(hash >> 8) % 30) // 60-90%
  const lightness = 45 + (Math.abs(hash >> 16) % 20) // 45-65%
  
  return hslToHex(hue, saturation, lightness)
}

// HSL转十六进制颜色
function hslToHex(h: number, s: number, l: number): THREE.Color {
  s /= 100
  l /= 100
  
  const c = (1 - Math.abs(2 * l - 1)) * s
  const x = c * (1 - Math.abs((h / 60) % 2 - 1))
  const m = l - c / 2
  
  let r = 0, g = 0, b = 0
  
  if (0 <= h && h < 60) {
    r = c; g = x; b = 0
  } else if (60 <= h && h < 120) {
    r = x; g = c; b = 0
  } else if (120 <= h && h < 180) {
    r = 0; g = c; b = x
  } else if (180 <= h && h < 240) {
    r = 0; g = x; b = c
  } else if (240 <= h && h < 300) {
    r = x; g = 0; b = c
  } else if (300 <= h && h < 360) {
    r = c; g = 0; b = x
  }
  
  r = Math.round((r + m) * 255)
  g = Math.round((g + m) * 255)
  b = Math.round((b + m) * 255)
  
  return new THREE.Color(r / 255, g / 255, b / 255)
}

// 创建国家网格
function createCountryMesh(coordinates: number[][], color: THREE.Color, countryName: string) {
  try {
    const points: THREE.Vector3[] = []
    
    // 将经纬度坐标转换为3D球面坐标
    coordinates.forEach((coord: number[], index: number) => {
      const [lon, lat] = coord
      
      // 调整经度范围到0-360度
      const normalizedLon = lon < 0 ? lon + 360 : lon;
      
      // 根据Three.js SphereGeometry的UV映射规则进行坐标转换
      // U坐标对应经度：0-360度映射到0-1
      // V坐标对应纬度：0-180度映射到0-1（从北极到南极）
      const u = normalizedLon / 360;
      const v = (90 - lat) / 180;  // 转换纬度到0-1范围
      
      // 计算球面坐标角度
      const phi = v * Math.PI;  // 纬度方向，0到π
      const theta = u * Math.PI * 2;  // 经度方向，0到2π
      
      // 调试输出（只输出第一个国家的第一个点）
      if (countryName === 'China' && index === 0) {
        console.log(`调试 ${countryName} 坐标转换:`, {
          原始坐标: [lon, lat],
          标准化经度: normalizedLon,
          u: u,
          v: v,
          phi: phi,
          theta: theta,
          最终位置: {
            x: 1.01 * Math.sin(phi) * Math.cos(theta),
            y: 1.01 * Math.cos(phi),
            z: 1.01 * Math.sin(phi) * Math.sin(theta)
          }
        })
      }
      
      // 稍微大于地球半径，确保地理层在地球表面
      const radius = 1.01
      
      // 球面坐标转直角坐标（与Three.js SphereGeometry保持一致）
      const x = -radius * Math.cos(theta) * Math.sin(phi)
      const y = radius * Math.cos(phi)
      const z = radius * Math.sin(theta) * Math.sin(phi)
      
      points.push(new THREE.Vector3(x, y, z))
    })
    
    // 创建填充区域
    if (points.length > 2) {
      // 使用球面三角化
      const triangles = sphericalTriangulation(points)
      
      if (triangles.length > 0) {
        const fillGeometry = new THREE.BufferGeometry()
        fillGeometry.setAttribute('position', new THREE.Float32BufferAttribute(triangles, 3))
        fillGeometry.computeVertexNormals()
        
        const fillMaterial = new THREE.MeshPhongMaterial({
          color: color,
          transparent: true,
          opacity: 0.7,
          side: THREE.DoubleSide,
          shininess: 10
        })
        
        const fillMesh = new THREE.Mesh(fillGeometry, fillMaterial)
        geoGroup.add(fillMesh)
      }
    }
    
    // 创建边界线
    const lineGeometry = new THREE.BufferGeometry().setFromPoints(points)
    const lineMaterial = new THREE.LineBasicMaterial({
      color: 0x000000,
      transparent: true,
      opacity: 0.3,
      linewidth: 1
    })
    
    const line = new THREE.Line(lineGeometry, lineMaterial)
    geoGroup.add(line)
    
  } catch (error) {
    console.warn(`创建国家 ${countryName} 失败:`, error)
  }
}

// 改进的球面三角化算法 - 使用更稳健的方法
function sphericalTriangulation(points: THREE.Vector3[]): number[] {
  if (points.length < 3) return []
  
  const vertices: number[] = []
  
  // 预处理：移除重复点和过近的点
  const filteredPoints = filterPoints(points)
  if (filteredPoints.length < 3) return []
  
  // 计算多边形的几何中心
  const center = calculateCentroid(filteredPoints)
  
  // 使用改进的三角化方法
  if (filteredPoints.length === 3) {
    // 三角形直接使用
    const p1 = filteredPoints[0].clone().normalize().multiplyScalar(1.01)
    const p2 = filteredPoints[1].clone().normalize().multiplyScalar(1.01)
    const p3 = filteredPoints[2].clone().normalize().multiplyScalar(1.01)
    
    vertices.push(
      p1.x, p1.y, p1.z,
      p2.x, p2.y, p2.z,
      p3.x, p3.y, p3.z
    )
  } else {
    // 对于多边形，使用中心点扇形三角化
    for (let i = 0; i < filteredPoints.length; i++) {
      const nextIndex = (i + 1) % filteredPoints.length
      
      const p1 = center.clone()
      const p2 = filteredPoints[i].clone().normalize().multiplyScalar(1.01)
      const p3 = filteredPoints[nextIndex].clone().normalize().multiplyScalar(1.01)
      
      vertices.push(
        p1.x, p1.y, p1.z,
        p2.x, p2.y, p2.z,
        p3.x, p3.y, p3.z
      )
    }
  }
  
  return vertices
}

// 过滤重复点和过近的点
function filterPoints(points: THREE.Vector3[]): THREE.Vector3[] {
  const filtered: THREE.Vector3[] = []
  const minDistance = 0.001
  
  for (let i = 0; i < points.length; i++) {
    const point = points[i]
    let shouldAdd = true
    
    // 检查是否与已添加的点太近
    for (const existing of filtered) {
      if (point.distanceTo(existing) < minDistance) {
        shouldAdd = false
        break
      }
    }
    
    if (shouldAdd) {
      filtered.push(point)
    }
  }
  
  return filtered
}

// 计算多边形的几何中心
function calculateCentroid(points: THREE.Vector3[]): THREE.Vector3 {
  const center = new THREE.Vector3(0, 0, 0)
  
  // 使用归一化的点计算中心
  points.forEach(point => {
    center.add(point.clone().normalize())
  })
  
  center.normalize()
  center.multiplyScalar(1.01)
  
  return center
}

// 检查多边形是否简单（无自相交）
function isSimplePolygon(points: THREE.Vector3[]): boolean {
  if (points.length < 4) return true
  
  // 简化检查：检查是否有重复点
  for (let i = 0; i < points.length; i++) {
    for (let j = i + 1; j < points.length; j++) {
      if (points[i].distanceTo(points[j]) < 0.001) {
        return false
      }
    }
  }
  
  return true
}

// 动画循环
function animate() {
  animationId = requestAnimationFrame(animate)

  // 地球自转
  if (isRotating.value && earth) {
    earth.rotation.y += 0.005
  }

  // 更新控制器
  controls.update()

  // 渲染场景
  renderer.render(scene, camera)
}

// 窗口大小调整
function handleResize() {
  if (!camera || !renderer) return
  
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}

// 控制函数
const toggleRotation = () => {
  isRotating.value = !isRotating.value
}

const resetView = () => {
  if (camera && controls) {
    camera.position.set(0, 0, 3)
    controls.reset()
  }
}

const toggleWireframe = () => {
  showWireframe.value = !showWireframe.value
  if (earthMaterial) {
    earthMaterial.wireframe = showWireframe.value
  }
}

const toggleTexture = () => {
  showTexture.value = !showTexture.value
  if (earthMaterial) {
    if (showTexture.value) {
      // 恢复纹理
      const textureLoader = new THREE.TextureLoader()
      earthMaterial.map = textureLoader.load(`${location.origin}/src/assets/img/earth.jpg`)
    } else {
      // 使用纯色
      earthMaterial.map = null
      earthMaterial.color = new THREE.Color(0x2e7d32) // 绿色
    }
    earthMaterial.needsUpdate = true
  }
}

const toggleGeoLayer = () => {
  showGeoLayer.value = !showGeoLayer.value
  if (geoGroup) {
    geoGroup.visible = showGeoLayer.value
  }
}

// 生命周期钩子
onMounted(() => {
  initScene()
  animate()
  
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  if (animationId) {
    cancelAnimationFrame(animationId)
  }
  
  window.removeEventListener('resize', handleResize)
  
  // 清理Three.js资源
  if (renderer) {
    renderer.dispose()
  }
  
  if (earth) {
    earth.geometry.dispose()
    if (earth.material instanceof THREE.Material) {
      earth.material.dispose()
    }
  }
})
</script>

<style scoped>
.earth-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background: linear-gradient(to bottom, #000814, #001d3d);
}

#opaque-earth-canvas {
  width: 100%;
  height: 100%;
}

.controls {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 100;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.controls button {
  padding: 12px 18px;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.3);
  color: white;
  border-radius: 8px;
  cursor: pointer;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
  font-size: 14px;
  font-weight: 500;
}

.controls button:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.controls button:active {
  transform: translateY(0);
}

.info {
  position: absolute;
  bottom: 20px;
  left: 20px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 14px;
  background: rgba(0, 0, 0, 0.3);
  padding: 10px 15px;
  border-radius: 8px;
  backdrop-filter: blur(10px);
}
</style>